from abc import ABCMeta, abstractmethod

from tornado.ioloop import IOLoop

from vnpy_ctp.core.monitor import BaseMonitor
from vnpy_ctp.core.object import List
from vnpy_ctp.utils.logger_util import get_logger


class BaseDataSource(metaclass=ABCMeta):
    logger = get_logger("BaseData")

    def __init__(self):
        self._monitors = List()

    def register_monitor(self, monitor: BaseMonitor):
        self.logger.info(f"register monitor: {monitor}")
        self._monitors.add_item(monitor)

    def unregister_monitor(self, monitor: BaseMonitor):
        self.logger.info(f"unregister monitor: {monitor}")
        self._monitors.rm_item(monitor)

    @abstractmethod
    def start(self):
        pass

    @abstractmethod
    def stop(self):
        pass

    async def notice_monitors(self, event_type, msg):
        for monitor in self._monitors.get_items():
            command_func = getattr(monitor, event_type, None)
            try:
                self.invoke_monitor_func(command_func, msg)
                await command_func(msg)
            except Exception as e:
                self.logger.error(e)

    def invoke_monitor_func(self, func, msg):
        IOLoop.current().spawn_callback(func, msg)

